/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package tablut;

//Voici la classe qui joue effectivement
//Pour donner le bon exemple, j'ai recopié en interne
//les méthodes permettant de jouer le coup. C'est à vous de les
//coder avec vos propres structures de données représentant le plateau
//de jeu.
public class JoueurAleatoire implements IJoueur {

        final int TAILLE = ReglesTablut.TAILLE;

        // constantes pour les pièces
        private final static int VIDE = 0;
        private final static int BLANC = 1;
        private final static int NOIR = 2;
        private final static int ROI = 3;

        private final static int CASEINTERDITE = 5;
        private final static int CASETRONE = 6;
        private final static int CASESORTIE = 7;

        // board
        private int placementPieces[][];
        private int typeCases[][];   // duration until timeout


        @SuppressWarnings("unused")
        private int tempsMaxPartie; // Pas utilisé ici...

        // what is my colour?
        private int maCouleur;
        private int couleurEnnemi;

        // has the game ended?
        private boolean partieTerminee = false;

        private int roiCol;

        private int roiLig;

        // who is the winner?
        @SuppressWarnings("unused")
        private int winner = 0;

        // who moves next?
        @SuppressWarnings("unused")
        private int joueurAJouer;

        // Constructeur d'un  joueur aléatoire...
        // J'ai repris la technique très simple utilisée dans l'arbitre
        // Pour vous, il sera peut-être préferable de ne pas utiliser deux tableaux...
        public JoueurAleatoire() {

                tempsMaxPartie = ReglesTablut.TEMPSMAXIMUM;

                placementPieces = new int[TAILLE][TAILLE];
                typeCases = new int[TAILLE][TAILLE];
                for(int i=0; i<TAILLE; i++)
                        for(int j=0; j< TAILLE; j++) {
                                placementPieces[i][j] = VIDE;
                                typeCases[i][j] = VIDE;
                        }

                // Les quatres cases des coins sont interdites, pour tout joueur
                // (sauf théoriquement pour le Roi, mais s'il peut s'y rendre,
                // il doit trouver un autre moyen de sortir !)
                typeCases[0][0] = CASEINTERDITE;
                typeCases[0][TAILLE-1] = CASEINTERDITE;
                typeCases[TAILLE-1][0] = CASEINTERDITE;
                typeCases[TAILLE-1][TAILLE-1] = CASEINTERDITE;


                typeCases[4][4] = CASETRONE;
                roiCol = 4;
                roiLig = 4;

                // On place les sorties possibles
                for(int i = 3; i< 6;  i++) {
                        typeCases[i][0] = CASESORTIE;
                        typeCases[0][i] = CASESORTIE;
                        typeCases[i][8] = CASESORTIE;
                        typeCases[8][i] = CASESORTIE;
                }


                // Une fois que le Roi aura quitté son trone,
                // Plus personne ne pourra aller en [4,4] (sauf lui)
                placementPieces[4][4] = ROI;

                // On place les attaquants sur les cotés
                for( int i = 3; i < 6; i++ ){
                        placementPieces[0][i] = NOIR;
                        placementPieces[TAILLE-1][i] = NOIR;
                        placementPieces[i][0] = NOIR;
                        placementPieces[i][TAILLE-1] = NOIR;
                }

                // Dernières pointes des attaquants
                placementPieces[4][1] = NOIR;
                placementPieces[1][4] = NOIR;
                placementPieces[TAILLE-2][4] = NOIR;
                placementPieces[4][TAILLE-2] = NOIR;


                // On place les défenseurs
                placementPieces[3][4] = BLANC;
                placementPieces[2][4] = BLANC;
                placementPieces[4][3] = BLANC;
                placementPieces[4][2] = BLANC;
                placementPieces[5][4] = BLANC;
                placementPieces[6][4] = BLANC;
                placementPieces[4][5] = BLANC;
                placementPieces[4][6] = BLANC;

                // Le premier joueur qui peut jouer est BLANC
                joueurAJouer = BLANC;
        }

        private void printPlateau(){
                for(int i=0;i<TAILLE;i++) {
                        for(int j=0;j<TAILLE;j++)
                                System.out.print(placementPieces[i][j]);
                        System.out.println();
                }
        }
        // Ceci est la fonction principale que vous devrez implanter.
        // Ici pour le joueur aléatoire, tout est très simple...
        // Mais pour vous... :)
        public String choixMouvement() {
                int lignePiece, colonnePiece, ligneDestination, colonneDestination;
                // Je sais que l'on pourrait faire mieux mais le random-player
                // va tirer au sort des mouvements en choisissant d'abord une case
                // puis une direction...
                System.out.println("Ah, c'est a moi, le joueur aleatoire " + maCouleur + " de jouer... Je réfléchis...");
                System.out.println("Voici mon plateau de jeu avant de choisir mon coup :");
                printPlateau();

                if (partieTerminee) {
                        System.out.println("On me demande de jouer alors que la partie est terminée !!");
                        return "0 0 0 0" + '\0';
                }

                {   // Vérifions d'abord si un mouvement est bien possible pour ne pas tourner en rond
                        boolean mouvementPossible = false;
                        int i=0;
                        int j;
                        while ((i<TAILLE) && !mouvementPossible) {
                                j = 0;
                                while ((j<TAILLE) && !mouvementPossible) {
                                        if ((placementPieces[i][j] == maCouleur)||(placementPieces[i][j] == ROI && maCouleur==BLANC))
                                                // Verifie si autour il n'y a pas une case vide
                                                if ( ((i>0) && (placementPieces[i-1][j] == VIDE) &&
                                                                (typeCases[i-1][j]!=CASETRONE) && (typeCases[i-1][j]!=CASEINTERDITE) ) ||
                                                                ((i<TAILLE-1) && (placementPieces[i+1][j] == VIDE) &&
                                                                                (typeCases[i+1][j]!=CASETRONE) && (typeCases[i+1][j]!=CASEINTERDITE) ) ||
                                                                                ((j>0) && (placementPieces[i][j-1] == VIDE) &&
                                                                                                (typeCases[i][j-1]!=CASETRONE) && (typeCases[i][j-1]!=CASEINTERDITE) ) ||
                                                                                                ((j<TAILLE-1) && (placementPieces[i][j+1] == VIDE) &&
                                                                                                                (typeCases[i][j+1]!=CASETRONE) && (typeCases[i][j+1]!=CASEINTERDITE) ) ) {
                                                        mouvementPossible = true;
                                                }
                                        j++;
                                }
                                i++;
                        }
                        if (!mouvementPossible) {// aucun mouvement possible...
                                System.out.println("Je dois bouger mais je sens que je suis bloqué... Match Nul ?");
                                System.out.println("Mon Mouvement : 0 0 0 0");
                                return "0 0 0 0" + '\0';

                        }
                }



                do{
                        do{
                                lignePiece = (int)(Math.random()*TAILLE);
                                colonnePiece = (int)(Math.random()*TAILLE);
                        } while((placementPieces[lignePiece][colonnePiece] != maCouleur) &&
                                        (placementPieces[lignePiece][colonnePiece] != ROI || maCouleur==NOIR));
                        // On a trouvé une piece...

                        // On choisit une ligne ou une colonne
                        if( Math.random()*2 < 1.0 ){
                                ligneDestination = (int)(Math.random()*TAILLE);
                                colonneDestination = colonnePiece;
                        }
                        else{
                                colonneDestination = (int)(Math.random()*TAILLE);
                                ligneDestination = lignePiece;
                        }
                } while( !estLegal( lignePiece, colonnePiece, ligneDestination, colonneDestination ) );

                // Voilà un mouvement aléatoire qu'il est bon !

                // Avant de le renvoyer, on le joue...
                executeMouvement(maCouleur, lignePiece,colonnePiece, ligneDestination, colonneDestination);

                String msg = "" + lignePiece + " " + colonnePiece + " " + ligneDestination + " " + colonneDestination + '\0';
                System.out.println("Voici mon mouvement : " + msg);
                System.out.println("Voici mon plateau de jeu apres mon coup :");
                printPlateau();

                return msg;
        }

        // C'est une fonction privée car c'est bien uniquement en interne que l'on fait le mouvement
        // On peut supposer que le mouvement est legal...
        // Il faut donc faire le mouvement et vérifier tout de même si des pions peuvent être pris,
        // ou si la partie est finie...
        private void executeMouvement(int couleur, int departLigne, int departColonne, int arriveeLigne, int arriveeColonne) {

                if ((departLigne == 0) && (departColonne == 0) &&
                                (arriveeLigne == 0) && (arriveeColonne == 0 ) )
                        return; // rien à faire, je ou ennemi ne bouge pas... et c'est légal...

                placementPieces[arriveeLigne][arriveeColonne] = placementPieces[departLigne][departColonne];
                placementPieces[departLigne][departColonne] = VIDE;

                // vérifions si le roi est capturé
                if (couleur == NOIR) {
                        if( //(typeCases[roiLig][roiCol] != CASETRONE) &&
                                        ((roiLig-1 >= 0 && ( placementPieces[roiLig-1][roiCol] == NOIR ||
                                                        typeCases[roiLig-1][roiCol] == CASETRONE )) ||
                                                        roiLig-1 < 0 ) &&
                                                        ((roiLig+1 < TAILLE && ( placementPieces[roiLig+1][roiCol] == NOIR ||
                                                                        typeCases[roiLig+1][roiCol] == CASETRONE)) ||
                                                                        roiLig+1 >= TAILLE ) &&
                                                                        ((roiCol-1 >= 0 && ( placementPieces[roiLig][roiCol-1] == NOIR ||
                                                                                        typeCases[roiLig][roiCol-1] == CASETRONE )) ||
                                                                                        roiCol-1 < 0 ) &&
                                                                                        ((roiCol+1 < TAILLE && ( placementPieces[roiLig][roiCol+1] == NOIR ||
                                                                                                        typeCases[roiLig][roiCol+1] == CASETRONE )) ||
                                                                                                        roiCol +1 >= TAILLE) ) {
                                // Ici on vient de capturer le roi !!!
                                if (maCouleur==BLANC) {
                                        System.out.println("Argh Je viens de me faire capturer le ROI :-(....");
                                } else {
                                        System.out.println("Chouette. Je viens enfin de capturer son ROI ;-)...");
                                }
                                System.out.println("Le roi etait en "+roiLig+","+roiCol+" et s'est fait capture.");
                                partieTerminee = true;
                                winner = couleur;
                                return;
                        }
                }

                // Est-ce un mouvement du Roi (peut-il s'enfuir ?)
                if (placementPieces[arriveeLigne][arriveeColonne] == ROI) { // il faut une maj
                        roiCol = arriveeColonne;
                        roiLig = arriveeLigne;
                        if (typeCases[roiLig][roiCol] == CASESORTIE) { // Le roi vient de s'enfuir
                                if (maCouleur==BLANC) {
                                        System.out.println("Chouette. Je viens de sauver mon ROI ;-)...");
                                } else {
                                        System.out.println("Argh. Ce maudit ROI vient de s'échapper...");
                                }
                                partieTerminee = true;
                                winner = couleur;
                                return;
                        }
                }

                // Ici on est sur que le roi ne peut être capturé. Il faut juste vérifier la capture des pièces
                if (couleur == BLANC) {// NOIR peut être pris entre BLANCs et ROI (le Roi est armé).
                        if( ( arriveeLigne-2 >= 0 && placementPieces[arriveeLigne-1][arriveeColonne] == NOIR ) &&
                                        ( placementPieces[arriveeLigne-2][arriveeColonne] == BLANC ||
                                                        typeCases[arriveeLigne-2][arriveeColonne] == CASETRONE ||
                                                        placementPieces[arriveeLigne-2][arriveeColonne] == ROI))
                                placementPieces[arriveeLigne-1][arriveeColonne] = VIDE;
                        if( ( arriveeLigne+2 < TAILLE && placementPieces[arriveeLigne+1][arriveeColonne] == NOIR ) &&
                                        ( placementPieces[arriveeLigne+2][arriveeColonne] == BLANC ||
                                                        typeCases[arriveeLigne+2][arriveeColonne] == CASETRONE ||
                                                        placementPieces[arriveeLigne+2][arriveeColonne] == ROI))
                                placementPieces[arriveeLigne+1][arriveeColonne] = VIDE;
                        if( ( arriveeColonne-2 >= 0 && placementPieces[arriveeLigne][arriveeColonne-1] == NOIR ) &&
                                        ( placementPieces[arriveeLigne][arriveeColonne-2] == BLANC ||
                                                        typeCases[arriveeLigne][arriveeColonne-2] == CASETRONE ||
                                                        placementPieces[arriveeLigne][arriveeColonne-2] == ROI))
                                placementPieces[arriveeLigne][arriveeColonne-1] = VIDE;
                        if( ( arriveeColonne+2 < TAILLE && placementPieces[arriveeLigne][arriveeColonne+1] == NOIR ) &&
                                        ( placementPieces[arriveeLigne][arriveeColonne+2] == BLANC ||
                                                        typeCases[arriveeLigne][arriveeColonne+2] == CASETRONE ||
                                                        placementPieces[arriveeLigne][arriveeColonne+2] == ROI))
                                placementPieces[arriveeLigne][arriveeColonne+1] = VIDE;
                } else { // couleur est noir. Pas la peine de vérifier que roi peut être pris (déjà fait)
                        if( ( arriveeLigne-2 >= 0 && placementPieces[arriveeLigne-1][arriveeColonne] == BLANC ) &&
                                        ( placementPieces[arriveeLigne-2][arriveeColonne] == NOIR ||
                                                        typeCases[arriveeLigne-2][arriveeColonne] == CASETRONE))
                                placementPieces[arriveeLigne-1][arriveeColonne] = VIDE;
                        if( ( arriveeLigne+2 < TAILLE && placementPieces[arriveeLigne+1][arriveeColonne] == BLANC ) &&
                                        ( placementPieces[arriveeLigne+2][arriveeColonne] == NOIR ||
                                                        typeCases[arriveeLigne+2][arriveeColonne] == CASETRONE))
                                placementPieces[arriveeLigne+1][arriveeColonne] = VIDE;
                        if( ( arriveeColonne-2 >= 0 && placementPieces[arriveeLigne][arriveeColonne-1] == BLANC ) &&
                                        ( placementPieces[arriveeLigne][arriveeColonne-2] == NOIR ||
                                                        typeCases[arriveeLigne][arriveeColonne-2] == CASETRONE))
                                placementPieces[arriveeLigne][arriveeColonne-1] = VIDE;
                        if( ( arriveeColonne+2 < TAILLE && placementPieces[arriveeLigne][arriveeColonne+1] == BLANC ) &&
                                        ( placementPieces[arriveeLigne][arriveeColonne+2] == NOIR ||
                                                        typeCases[arriveeLigne][arriveeColonne+2] == CASETRONE))
                                placementPieces[arriveeLigne][arriveeColonne+1] = VIDE;

                }
        }

        public void declareLeVainqueur(int colour) {
                partieTerminee = true;
                winner = colour;
        }


        // On suppose ici que le mouvement est bien légal.
        public void mouvementEnnemi(int startRow, int startCol, int finishRow, int finishCol) {
                System.out.println("On vient de me dire que Ennemi avait joué.");
                executeMouvement(couleurEnnemi, startRow, startCol, finishRow, finishCol);
                System.out.println("Voici mon plateau de jeu apres le coup de ennemi:");
                printPlateau();

        }



        // Cette méthode ne sert pas à vérifier les coups ennemis,
        // mais a vérifier qu'un coup aléatoire est bien légal
        // Le coup qui doit etre testé est donc obligatoirement un coup avec couleur==macouleur
        private boolean estLegal( int departLigne, int departColonne, int arriveeLigne, int arriveeColonne ){

                if ((departLigne == 0) && (departColonne == 0) &&
                                (arriveeLigne == 0) && (arriveeColonne == 0 ) ) { // Mouvement Nul
                        // Il faut vérifier qu'effectivement aucun mouvement n'est possible
                        // pour joueurAJouer
                        for(int i=0;i < TAILLE; i++)
                                for(int j=0; j< TAILLE; j++)
                                        if (placementPieces[i][j] == maCouleur)
                                                // Verifie si autour il n'y a aucune case vide
                                                if ( ((i>0) && (placementPieces[i-1][j] == VIDE) &&
                                                                (typeCases[i-1][j]!=CASETRONE) && (typeCases[i-1][j]!=CASEINTERDITE) )
                                                                || ((i<TAILLE-1) && (placementPieces[i+1][j] == VIDE) &&
                                                                                (typeCases[i+1][j]!=CASETRONE) && (typeCases[i+1][j]!=CASEINTERDITE) )
                                                                                || ((j>0) && (placementPieces[i][j-1] == VIDE) &&
                                                                                                (typeCases[i][j-1]!=CASETRONE) && (typeCases[i][j-1]!=CASEINTERDITE) )
                                                                                                || ((j<TAILLE-1) && (placementPieces[i][j+1] == VIDE) &&
                                                                                                                (typeCases[i][j+1]!=CASETRONE) && (typeCases[i][j+1]!=CASEINTERDITE) ) ) {
                                                        return false;
                                                }
                        return true;
                }

                // Est-ce que la bonne couleur joue ?
                // Est-ce qu'on trouve la bonne couleur au départ ?
                // Est-ce que l'on bouge vraiment ?
                if( (maCouleur == NOIR && placementPieces[departLigne][departColonne] != maCouleur ) ||
                                (maCouleur == BLANC && ( placementPieces[departLigne][departColonne] != maCouleur &&
                                                placementPieces[departLigne][departColonne] != ROI )) ||
                                                (departLigne == arriveeLigne && departColonne == arriveeColonne) ){
                        return false;
                }

                // Si c'est une case spéciale, personne ne peut y aller
                if ((typeCases[arriveeLigne][arriveeColonne] == CASEINTERDITE) ||
                                (typeCases[arriveeLigne][arriveeColonne] == CASETRONE) )
                                return false;

                // Est-ce que le mouvement est bien horizontal ou vertical...
                if( departLigne == arriveeLigne || departColonne == arriveeColonne ){
                        if( departLigne == arriveeLigne ){ // Le long d'une ligne
                                // Vérifions qu'il n'y a pas de pièces le long de la trajectoire
                                int decal;
                                if (departColonne < arriveeColonne) decal = 1;
                                else decal = -1;
                                for(int i = departColonne+decal; i!= (arriveeColonne+decal); i+=decal) {
                                        if (placementPieces[departLigne][i] != VIDE )
                                                return false;
                                }
                                return true;
                        } else { // Le long d'une colonne
                                int decal;
                                if (departLigne < arriveeLigne) decal = 1;
                                else decal = -1;
                                for( int i = departLigne+decal; i != (arriveeLigne+decal); i+=decal ){
                                        if( placementPieces[i][departColonne] != VIDE )
                                                return false;
                                }
                                return true;
                        }
                }
                else{ // Mouvement Diagonal
                        return false;
                }
        }


        public void initJoueur(int mycolour) {
                maCouleur = mycolour;
                if (mycolour == BLANC)
                        couleurEnnemi = NOIR;
                else
                        couleurEnnemi = BLANC;


        }

        public String quadriName() {
                return "JoueurAleatoire";
        }


}

